﻿using MainFrame.Common.Interface;
using Qianke.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Unity;
using Unity.Lifetime;

namespace MainFrame.Common
{
    public static class UnityHelper
    {

        public static IUnityContainer unityContainer = new UnityContainer();

        public static Dictionary<string,Type> RegisterTypeArray { set; get; } = new Dictionary<string,Type>();

        private static void LoadFormAssembly(Assembly assembly)
        {
            try
            {
                foreach (Type type in assembly.GetExportedTypes())
                {
                    if (!type.IsClass || type.IsAbstract)
                        continue;
                    if (type.GetInterfaces().Any(z => z == typeof(IScopedDependency)))
                    {
                        RegisterScoped(type);
                        Type interfaceType = type.GetInterface("I" + type.Name);
                        if (interfaceType != null)
                            RegisterScoped(interfaceType, type);
                    }
                    if (type.GetInterfaces().Any(z => z == typeof(ISingletonDependency)))
                    {
                        RegisterSingleton(type);
                        Type interfaceType = type.GetInterface("I" + type.Name);
                        if (interfaceType != null)
                            RegisterSingleton(interfaceType, type);
                    }
                    if (type.GetInterfaces().Any(z => z == typeof(ITransientDependency)))
                    {
                        RegisterTransient(type);
                        Type interfaceType = type.GetInterface("I" + type.Name);
                        if (interfaceType != null)
                            RegisterTransient(interfaceType, type);
                    }
                    RegisterTypeArray.Add(type.Name, type);
                }
            }
            catch (Exception ex)
            {
               // Trace.WriteLine($"程序集：{assembly.FullName}初始化注入遇到异常:" + ex.Message);
            }
        }

        public static void LoadDllFromDirectory(string directory)
        {
            // 遍历指定目录下所有程序集  
            foreach (string assemblyPath in Directory.GetFiles(directory, "*.dll"))
            {
                try
                {
                    // 使用Reflection加载程序集  
                    Assembly assembly = Assembly.LoadFrom(assemblyPath);
                    // 获取程序集中的所有类型  
                    LoadFormAssembly(assembly);
                }
                catch
                {

                }
            }
        }

        static UnityHelper()
        {
            //加载当前程序所有程序集
            //foreach(var assembly  in AppDomain.CurrentDomain.GetAssemblies())
            //{
            //    Trace.WriteLine(assembly.FullName);
            //    LoadFormAssembly(assembly);
            //}
            var dir = AppDomain.CurrentDomain.BaseDirectory;
            LoadDllFromDirectory(dir);
        }

        /// <summary>
        /// 单例模式 注入
        /// </summary>
        /// <typeparam name="ITModel"></typeparam>
        /// <typeparam name="TModel"></typeparam>
        public static void RegisterSingleton<ITModel, TModel>()
            where TModel : ITModel
        {
            unityContainer.RegisterType<ITModel, TModel>(new SingletonLifetimeManager());
        }

        public static void RegisterSingleton(Type type)
        {
            unityContainer.RegisterType(type, new SingletonLifetimeManager());
        }

        public static void RegisterSingleton(Type tfrom, Type tto)
        {
            unityContainer.RegisterType(tfrom, tto, new SingletonLifetimeManager());
        }

        /// <summary>
        /// 瞬时模式 注入
        /// </summary>
        /// <typeparam name="ITModel"></typeparam>
        /// <typeparam name="TModel"></typeparam>
        public static void RegisterTransient<ITModel, TModel>()
            where TModel : ITModel
        {
            unityContainer.RegisterType<ITModel, TModel>(new TransientLifetimeManager());
        }
        public static void RegisterTransient(Type type)
        {
            unityContainer.RegisterType(type, new TransientLifetimeManager());
        }
        public static void RegisterTransient(Type tfrom, Type tto)
        {
            unityContainer.RegisterType(tfrom, tto, new TransientLifetimeManager());
        }

        /// <summary>
        /// 作用域模式 注入
        /// </summary>
        /// <typeparam name="ITModel"></typeparam>
        /// <typeparam name="TModel"></typeparam>
        public static void RegisterScoped<ITModel, TModel>()
            where TModel : ITModel
        {
            unityContainer.RegisterType<ITModel, TModel>(new HierarchicalLifetimeManager());
        }

        public static void RegisterScoped(Type type)
        {
            unityContainer.RegisterType(type, new HierarchicalLifetimeManager());
        }
        public static void RegisterScoped(Type tfrom, Type tto)
        {
            unityContainer.RegisterType(tfrom, tto, new HierarchicalLifetimeManager());
        }


        public static IUnityContainer GetContainer()
        {
            var unity = unityContainer.CreateChildContainer();
            var serviceContainer = unity.GetService<IServiceContainer>();
            serviceContainer.SetContainer(unity);
            return unity;
        }
        public static TService GetService<TService>(this IUnityContainer container)
        {
            return container.Resolve<TService>();
        }



        //public static TService GetService<TService>(this IController context)
        //{
        //    return context.Controller.GetService<TService>();
        //}


        private static Dictionary<IController, IUnityContainer> dict = new System.Collections.Generic.Dictionary<IController, IUnityContainer>();

        public static TService GetService<TService>(this IController controller)
        {
            lock (dict)
            {
                var container = dict.GetValue(controller);
                if (container == null)
                    return default(TService);
                return container.Resolve<TService>();
            }
        }

        public static void SetServiceContainer(this IController controller, IUnityContainer container)
        {
            lock (dict)
                dict[controller] = container;
        }

        public static void ReleaseContainer(this IController controller)
        {
            lock (dict)
            {
                if (dict.ContainsKey(controller))
                    dict.Remove(controller);
            }
        }



    }
}
